import { useEffect, useMemo, useState } from 'react';
import clsx from 'clsx';
import { createPortal } from 'react-dom';
import Button from '@mui/material/Button';
import Box from '@mui/material/Box';
import CloseIcon from '@mui/icons-material/Close';
import { Input } from '@mui/base/Input';
import IconButton from '@mui/material/IconButton';
import { CircularProgress } from '@mui/material';
import { AlertDialogIconButton, message } from '@/compnents';
import { useApiPoiSearch } from '@/hooks';
import { addMarker, deleteMarker, editMarker, findAllMarker, findMarker, formatPoi, IApiFindMarkerResult } from '@/api';
import { useAppStore } from '@/stores';
import { genFileRecord, Upload } from '../upload';
import { ColorfulList } from '../colorful';
import { IconOutline, type IIconOutlineProps } from '../icon-library';
import { prefixCls } from './utils';
import { MarkerDeleteIcon, EditGeomIcon, MarkerEditIcon } from '../icons';
import type { IMarkerFeatureProperties } from '@/compnents';
import type { IFileRecord, IUploadProps } from '../upload';
import './marker-feature.less';

const eventTypes = ['markerFeature.create', 'markerFeature.edit', 'markerFeature.find', 'markerFeature.editFeature'];

export const MarkerFeaturePopup = () => {
  const map = useAppStore.use.map()!;
  const mfe = useAppStore.use.markerFeatureEvent();
  const { run } = useApiPoiSearch();
  const container = useMemo(() => {
    if (eventTypes.includes(mfe?.type ?? '')) return map.markerFeature.marker.getContainer();
  }, [mfe]);
  const mfLoaded = mfe?.type === 'markerFeature.loaded';
  const [poi, setPoi] = useState({ name: '', address: '' });
  const [markerRecord, setMarkerRecord] = useState<IApiFindMarkerResult['data']>();
  const [selectedIconImage, setSelectedIconImage] = useState('');
  const [color, setColor] = useState('');
  const [fileList, setFileList] = useState<IFileRecord[]>([]);
  const [loading, setLoading] = useState(false);

  const updateProperties = (params: Omit<IMarkerFeatureProperties, 'id'>) => {
    if (params.iconImage) map.iconImage.updateIconImage({ iconImage: params.iconImage, color: params.color });
    map.markerFeature.source.updateFeatureProperties({
      where: { properties: { id: map.markerFeature.groupId } },
      properties: { ...params },
    });
  };

  const onIconColorChange = (value: string) => {
    setColor(value);
    updateProperties({ iconImage: selectedIconImage, color: value });
  };

  const onSelectIconClick = () => {};

  const onIconChange: IIconOutlineProps['onChange'] = async (params) => {
    if (!params) return;
    setSelectedIconImage(params.iconImage);
    updateProperties({ iconImage: params.iconImage, color });
  };

  const onUploadChange: IUploadProps['onChange'] = async (data) => {
    setFileList(data ?? []);
  };

  const resetState = () => {
    setPoi({ name: '', address: '' });
    setColor('');
    setSelectedIconImage('');
    setFileList([]);
    setMarkerRecord(undefined);
  };

  const onCancel = () => {
    const id = map.markerFeature.groupId!;
    if (mfe!.type === 'markerFeature.create') {
      map.markerFeature.source.deleteData({ where: { properties: { id } } });
    } else if (mfe!.type === 'markerFeature.find' && markerRecord) {
      map.markerFeature.source.updateFeatureProperties({
        where: { properties: { id } },
        properties: map.markerFeature.genFeatureProperties({ ...markerRecord, id: markerRecord.id }),
      });
    }
    map.markerFeature.cancel();
    resetState();
  };

  const onSave = async () => {
    try {
      setLoading(true);
      const fc = map.markerFeature.source.findData({ properties: { id: map.markerFeature.groupId } });
      if (!fc.features.length) return message.error({ content: '未找到标记' });
      const p = {
        id: map.markerFeature.groupId!,
        name: poi.name,
        address: poi.address,
        color,
        iconImage: selectedIconImage ?? '',
        fileList,
        geometry: fc.features.length === 1 ? fc.features[0].geometry : fc.features.find((v) => v.geometry.type !== 'Point')!.geometry,
      };
      if (mfe!.type === 'markerFeature.edit' || mfe!.type === 'markerFeature.editFeature') {
        const res = await editMarker({ ...p });
        if (!res?.success) return message.error({ content: `编辑标记失败：${res?.message ?? ''}` });
        map.markerFeature.cancel();
        resetState();
        return message.success({ content: '保存成功' });
      }
      if (mfe!.type === 'markerFeature.create') {
        const res = await addMarker(p);
        if (!res?.success) return message.error({ content: `创建标记失败：${res?.message ?? ''}` });
        map.markerFeature.cancel();
        resetState();
        return message.success({ content: '保存成功' });
      }
    } catch (e) {
      console.error(e);
    } finally {
      setLoading(false);
    }
  };

  const onDeleteClick = async () => {
    const id = map.markerFeature.groupId!;
    const res = await deleteMarker(id);
    if (!res.success) return message.error({ content: `删除失败：${res.message ?? ''}` });
    message.success({ content: '删除成功' });
    map.markerFeature.source.deleteData({ where: { properties: { id } } });
    map.markerFeature.cancel();
  };

  const onEditClick = () => {
    map.markerFeature.edit();
  };

  const onEditGeometry = () => {
    const [feature] = map.markerFeature.source.findData({ properties: { id: map.markerFeature.groupId } }).features as any;
    if (feature) map.markerFeature.editFeature({ feature });
  };

  const renderHeader = (title: string) => {
    return (
      <div className={`${prefixCls}-header`}>
        <div className="smap-ellipsis marker-title">{title}</div>
        <IconButton onClick={onCancel}>
          <CloseIcon />
        </IconButton>
      </div>
    );
  };

  useEffect(() => {
    const update = async () => {
      try {
        if (!container || !mfe) return;
        setLoading(true);
        if (mfe.type === 'markerFeature.create') {
          const { properties } = mfe.featureCollection.features[0];
          setColor(properties.color);
          setSelectedIconImage(properties.iconImage);
          const res = await run({ ...map.markerFeature.marker.getLngLat() });
          if (res?.result) setPoi(formatPoi(res.result));
          return;
        }
        if (mfe.type === 'markerFeature.find' || mfe.type === 'markerFeature.edit' || mfe.type === 'markerFeature.editFeature') {
          const { properties } = mfe.featureCollection.features[0];
          setColor(properties.color);
          setSelectedIconImage(properties.iconImage);
          const res = await findMarker({ id: properties.id });
          if (res.data) {
            if (mfe.type === 'markerFeature.editFeature') {
              const poiRes = await run({ ...map.markerFeature.marker.getLngLat() });
              if (poiRes?.result) {
                const newPoi = formatPoi(poiRes.result);
                setPoi(newPoi);
                setMarkerRecord({ ...res.data, ...newPoi });
              }
            } else {
              setPoi({ name: res.data.name, address: res.data.address });
              setMarkerRecord(res.data);
            }
            if (Array.isArray(res.data.attachments)) {
              setFileList(res.data.attachments.map((v) => genFileRecord(v.file, { uid: v.id })));
            }
          }
        }
      } catch (e) {
        console.error(e);
      } finally {
        setLoading(false);
      }
    };
    update();
  }, [container, mfe]);

  useEffect(() => {
    const query = async () => {
      const res = await findAllMarker();
      if (Array.isArray(res?.data)) {
        res.data.forEach((item) => map.iconImage.updateIconImage(item));
        map.markerFeature.source.setData(map.markerFeature.genSourceData(res.data));
      }
    };
    if (mfLoaded) query();
  }, [mfLoaded]);

  if (!container || !map || !mfe) return null;
  if (mfe.type === 'markerFeature.find') {
    return createPortal(
      <Box className={clsx(prefixCls, 'find-marker')} sx={{ [`.${prefixCls}-header .MuiIconButton-root`]: { padding: 0 } }}>
        {renderHeader(poi.name)}
        <div className="marker-desc">{poi.address}</div>

        <div className={`${prefixCls}-footer`}>
          <IconButton className="label-btn" onClick={onEditClick}>
            <MarkerEditIcon />
            <div className="label-text">编辑属性</div>
          </IconButton>

          <IconButton className="label-btn" onClick={onEditGeometry}>
            <EditGeomIcon />
            <div className="label-text">编辑图形</div>
          </IconButton>

          <AlertDialogIconButton className="label-btn" alertDialogProps={{ title: '确定要删除这个标记吗？', onConfirm: onDeleteClick }}>
            <MarkerDeleteIcon />
            <div className="label-text">删除</div>
          </AlertDialogIconButton>
        </div>
      </Box>,
      container,
    );
  }
  return (
    <>
      {createPortal(
        <Box
          sx={{
            [`.${prefixCls}-footer .MuiButton-root, .base-Input-root`]: { flex: 1 },
            '.base-Input-input': {
              width: '100%',
              textAlign: 'right',
              border: 'none',
              color: 'rgba(0,0,0,.6)',
              'white-space': 'nowrap',
              overflow: 'hidden',
              'text-overflow': 'ellipsis',
            },
          }}
          className={clsx(prefixCls, {
            'create-marker': mfe.type === 'markerFeature.create',
            'edit-marker': mfe.type === 'markerFeature.edit',
            'edit-feature': mfe.type === 'markerFeature.editFeature',
          })}
        >
          {renderHeader('编辑地点信息')}
          <div className={`${prefixCls}-body`}>
            <div className={`${prefixCls}-item`}>
              <div className="marker-name">名称</div>
              <div className="marker-value">
                <Input onChange={(e) => setPoi((v) => ({ ...v, name: e.target.value }))} value={poi.name} />
              </div>
            </div>

            <div className={clsx(`${prefixCls}-item`, 'marker-address')} onClick={onEditGeometry}>
              <div className="marker-name">地址</div>
              <div className="marker-value">
                <Input value={poi.address} readOnly />
              </div>
            </div>

            <div className={`${prefixCls}-item`}>
              <div className="marker-name">颜色</div>
              <ColorfulList className="marker-value" value={color} onChange={onIconColorChange} />
            </div>
            <div className={`${prefixCls}-item`} onClick={onSelectIconClick}>
              <div className="marker-name">图标</div>
              <IconOutline className="marker-value" selectedIconImage={selectedIconImage} onChange={onIconChange} />
            </div>

            <div className={`${prefixCls}-item photo`}>
              <div className="marker-name">照片</div>
              <Upload className="marker-value" fileList={fileList} onChange={onUploadChange} />
            </div>
          </div>

          <div className={`${prefixCls}-footer`}>
            <Button variant="outlined" onClick={onCancel}>
              取消
            </Button>
            <Button
              startIcon={loading ? <CircularProgress size={16} /> : undefined}
              disabled={loading}
              variant="contained"
              onClick={onSave}
            >
              保存
            </Button>
          </div>
        </Box>,
        container,
      )}
    </>
  );
};
